import javax.sound.midi.Soundbank;

//      认识String类

//      注 看String的板书复习 看图（画图）理解  不然太抽象了
public class TestDemo2 {
    public static void main1(String[] args) {

//        构造String的方式
//        1.
        String str1 = "qwe";
//        2.调用构造方法进行构造对象
        String str2 = new String("hello");
//        3.
        char[] chars = {'a','b','c'};
        String str3 = new String(chars);
        System.out.println(str3);
    }


    public static void main2(String[] args) {
        String str1 = "qwe";
        String str2 = str1;
//        指向同一个地址(堆上qwe地址)
        System.out.println(str1);
        System.out.println(str2);
        System.out.println("==============");
        str1 = "zxc"; //这里是修改str1的指向 不是去修改里面的内容
        System.out.println(str1);//zxc
        System.out.println(str2);//qwe
//        我们发现, "修改" str1 之后, str2 也没发生变化
//        事实上, str1 = "zxc" 这样的代码并不算 "修改" 字符串, 而是让 str1 这个引用指向了一个新的 String 对象
    }




    public static void func(String arr,char[] chars){
        arr = "cat";  //  str穿到这时是先指向dog地址  然后在修改arr的指向 而不是去修改里面的内容
        chars[0] = 'b';// 通过地址访问0下标 进行修改
    }
    public static void main3(String[] args) {
        String str1 = "dog";
        char[] chars= {'p','i','g'};
        System.out.println(str1);
        System.out.println(chars);
        System.out.println("==============");
        func(str1,chars);
        System.out.println(str1);//dog
        System.out.println(chars);//big
    }


//    概念
//    Class文件(字节码文件)常量值：int a = 10;磁盘上
//    运行时常量池：当程序把编译好的字节码文件 加载到JVM当中后 会生成一个运行时常量池[方法区]
//    实际上是Class文件常量池
//    字符串常量池：主要存放字符串常量-》字符串常量池 本质上是一个哈希表StringTable
//    双引号引起来的字符串常量会放到字符串常量池  JDK1.8开始 哈希表在堆上存放字符串常量

//    什么是池
//    "池" 是编程中的一种常见的, 重要的提升效率的方式,
//    我们会在未来的学习中遇到各种 "内存池", "线程池", "数据库连接池"
//    1.数据库连接池
//    2.线程池
//    ......（数据如果池里面有就不放 没有就放）
//    意义：提高效率

//    什么是哈希表：数据结构-》描述和组织数据的一种方式
//    存储数据的时候 会根据一个映射关系进行存储 如何映射 需要设计一个函数(哈希函数（有许多） key%len（链表存储）)
    public static void main4(String[] args) {
        String str1 = "hello";
        String str2 = new String("hello");
//        str1已经存到hash  str又new一块空间在堆上 因为哈希表内已经有hello 使用new的空间在堆上 指向哈希表的hello地址
    }


    public static void main5(String[] args) {
        String str1 = "hello";
        String str2 = "hello";
        System.out.println(str1 == str2);//true

    }


    public static void main6(String[] args) {
//        此时它两都是常量 编译的时候 就已经确定好 是hello了
        String str1 = "hello";
        String str2 = "he"+"llo";
        System.out.println(str1 == str2);//true
        System.out.println("==================");
        String str3 = "he";
        String str4 = str3 + "llo";//此时str3是一个变量-》编译的时候 不知道是啥
//      str3和llo拼接的是单独的对象
        System.out.println(str3 == str4);//false
    }

    public static void main7(String[] args) {
        String str1 = "11"; //如果哈希表没有"11"就存入
        String str2 = new String("1") + new String("1");
//        new了两个对象  但是"1"值在哈希表中 两个对象都指向"1"的地址
//        它们两会在StingBuilder当中拼接(当中的val指向拼接好的那个"11"的地址)  因为在StingBuilder拼接完的类型是StingBuilder
//        使用StingBuilder会通过toString()方法 创建一个String空间 指向拼接好"11"的地址  还是通过图好理解 这里可以不看
        System.out.println(str1 == str2);//false
    }


    public static void main8(String[] args) {
        String str2 = new String("1") + new String("1");
        str2.intern();//手动入池  str2在堆内 哈希表外产生的值
        String str1 = "11";//先判断哈希表里面是否有"11"  如果没有就入池
        System.out.println(str1 == str2);
    }


    public static void main9(String[] args) {
        String str1 = null;
        String str2 = "cat";
        System.out.println(str1.equals(str2));//空指针异常 .q前面不能为空
        System.out.println(str2.equals(str1));
    }


    public static void main10(String[] args) {
//        数组的整体赋值 只有一次机会 就是在定义的时候
//        但是我们可以人该数组指向其他对象
        int[] arr = {1,2,3,4,5};
//        arr = {6,7,8}; err
        arr = new int[]{6,7,8,9,};
//        如果数组被final修饰 那么arr也不能指向新的对象
        System.out.println("==============");
        final int[] arr2 = {123,234,354};
//        arr2 = new int[]{6,7,8,9,};err
    }


//    字符串传参的注意点
    public static void func(String str){
//        1.
        if (str == null || str.length() == 0){
        }//正确的
        if (str.length() == 0 || str == null){
        }//错误的 str如果为空可能导致空指针异常

//        2.断言
//        assert str != null; 基本不用 要使用可以去idea里面设置 通常我们使用异常
    }

    public static void main(String[] args) {
        String str1 = null;//str1这个引用 不指向任何对象
        String str2 = "";//str2这个引用 指向的字符串是空的
        System.out.println(str2.length());//  0
    }
}
